import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

/**
 * $ cmd [-v] filename B1 B2 B3 B4
	cmd: "estimate" if you use C++, or "java Estimate" if you use Java; see below
	-v: verbose mode
	filename: file to read data set from
	B1: an integer
	B2: an integer
	B3: an integer
	B4: an integer
 *
 */
public class Optimizer {
	
	public static void main(String[] args) throws IOException, NoSuchElementException {
		
		boolean verbose = false;
		int B1, B2, B3, B4;	
		
		String filename;
		
		if (args.length < 1){
			System.out.println("YO MAN GIVE ME THE ARGUMENT!");
		}
				
		// if verbose
		if (args[0].equals("-v")) {
			verbose = true;
			
			filename = args[1];
			B1 = Integer.parseInt(args[2]);
			B2 = Integer.parseInt(args[3]);
			B3 = Integer.parseInt(args[4]);
			B4 = Integer.parseInt(args[5]);
		}
			
		else {
			filename = args[0];
			B1 = Integer.parseInt(args[1]);
			B2 = Integer.parseInt(args[2]);
			B3 = Integer.parseInt(args[3]);
			B4 = Integer.parseInt(args[4]);
		}
		
		ArrayList<Tuple> r = new ArrayList<Tuple>();
		// fill in R
        BufferedReader in = new BufferedReader(new FileReader(filename)); 		
        while (in.ready()) {
            	 String tuple = in.readLine();
            	 StringTokenizer tokenizer = new java.util.StringTokenizer(tuple, ",");
            	 String a1 = tokenizer.nextToken();
            	 String a2 = tokenizer.nextToken();
            	 r.add(new Tuple(Integer.parseInt(a1), Integer.parseInt(a2)));
        }

        in.close();
		
        
        InputStreamReader isr = new InputStreamReader( System.in );
	    BufferedReader stdin = new BufferedReader( isr );
	    
	    boolean running = true;
	    while (running) {
	    	System.out.println("Please enter the r1 s1 r2 s2");
		    String input = stdin.readLine();
		    if (input.equalsIgnoreCase("quit")) {
		    	running = false;
		    	continue;
		    }
	
		    StringTokenizer queryParser = new StringTokenizer(input);
		    int r1 = Integer.parseInt(queryParser.nextToken());
		    int s1 = Integer.parseInt(queryParser.nextToken());
		    int r2 = Integer.parseInt(queryParser.nextToken());
		    int s2 = Integer.parseInt(queryParser.nextToken());
		    
		    System.out.println(">" + r1 +  " " + s1 +  " " + r2 + " "  + s2);
	        
		 // get set1 result:
			Stat1 stat1 = new Stat1(r, verbose);
			double rfA1_set1 = stat1.getReductionFactor(r1, s1, "A1");
			double rfA2_set2 = stat1.getReductionFactor(r2, s2, "A2");
			double sizeEstimate = (stat1.count() * rfA1_set1) * rfA2_set2;
			System.out.println("Set 1 result est. size: (rf * rf) * size =  " + (int) Math.ceil((sizeEstimate)) + " \n----------------");
			
			// get set2 result
			Stat2 stat2 = new Stat2(r, B1, B2, verbose);
			double countA1_set2 = stat2.getEstimatedCount(r1, s1, "A1");
			double rf_A1_set2 = countA1_set2 / stat1.count();
			double countA2_set2 = stat2.getEstimatedCount(r2, s2, "A2");
			double rf_A2_set2 = countA2_set2 / stat1.count();
			sizeEstimate = rf_A1_set2 * rf_A2_set2 * stat1.count(); 
			System.out.println("Set 2 result est. size: rf * rf * size = " + (int) sizeEstimate + "\n-------------");
			
			// get set3 result 
			Stat3 stat3 = new Stat3(r, B3, B4);
			stat3.populateHistogram(verbose);
			double stat3estimate = stat3.returnEstimate(r1,s1,r2,s2, verbose);
			double stat3rf       = stat3estimate / stat1.count();
			System.out.println("Set 3 result size: " + (int)stat3estimate + " \n ----------------");
			//System.out.println("Set 3 result reductcion: " + (int) stat3rf); 
			
			
			// get tuples in matching query
			QueryMatch querymatch = new QueryMatch();
			double exactMatch = querymatch.exactMatch(r, r1, s1, r2, s2, verbose);
			double rf_exact   = exactMatch / (double)stat1.count();
			System.out.println("Exact result size: " + (int) exactMatch);
			//System.out.println("reduction factor: " + rf_exact);
	    }
	}
}
